
package game;



public class Plateau
{

	private Case[][] plateau;

	/**
	 * construit un tableau a deux dimension de case qui sera le plateau de scrabble
	 */
	public Plateau()
	{
		plateau=new Case[15][15];

		for(int i=0;i<15;i++)
		{
			for(int j=0;j<15;j++)
			{      
				plateau[i][j]=new Case(i, j, Case.NORMAL);
			}
		}
		init_plateau();
	}


	/**
	 * initialise les cases speciale du plateau
	 */
	private void init_plateau() {
		//mot compte triple
		plateau[0][0].SetType(Case.MTRIPLE);
		plateau[0][7].SetType(Case.MTRIPLE);
		plateau[0][14].SetType(Case.MTRIPLE);
		plateau[7][0].SetType(Case.MTRIPLE);
		plateau[14][0].SetType(Case.MTRIPLE);
		plateau[7][14].SetType(Case.MTRIPLE);
		plateau[14][7].SetType(Case.MTRIPLE);
		plateau[14][14].SetType(Case.MTRIPLE);
		//lettre compte triple
		plateau[1][5].SetType(Case.LTRIPLE);
		plateau[1][9].SetType(Case.LTRIPLE);
		plateau[5][1].SetType(Case.LTRIPLE);
		plateau[5][5].SetType(Case.LTRIPLE);
		plateau[5][9].SetType(Case.LTRIPLE);
		plateau[5][13].SetType(Case.LTRIPLE);
		plateau[9][1].SetType(Case.LTRIPLE);
		plateau[9][5].SetType(Case.LTRIPLE);
		plateau[9][9].SetType(Case.LTRIPLE);
		plateau[9][13].SetType(Case.LTRIPLE);
		plateau[13][5].SetType(Case.LTRIPLE);
		plateau[13][9].SetType(Case.LTRIPLE);
		//lettre compte double
		plateau[0][3].SetType(Case.LDOUBLE);
		plateau[0][11].SetType(Case.LDOUBLE);
		plateau[14][3].SetType(Case.LDOUBLE);
		plateau[14][11].SetType(Case.LDOUBLE);
		plateau[2][8].SetType(Case.LDOUBLE);
		plateau[2][6].SetType(Case.LDOUBLE);
		plateau[12][8].SetType(Case.LDOUBLE);
		plateau[12][6].SetType(Case.LDOUBLE);
		plateau[3][0].SetType(Case.LDOUBLE);
		plateau[3][7].SetType(Case.LDOUBLE);
		plateau[3][14].SetType(Case.LDOUBLE);
		plateau[11][0].SetType(Case.LDOUBLE);
		plateau[11][7].SetType(Case.LDOUBLE);
		plateau[11][14].SetType(Case.LDOUBLE);
		plateau[6][2].SetType(Case.LDOUBLE);
		plateau[6][6].SetType(Case.LDOUBLE);
		plateau[6][8].SetType(Case.LDOUBLE);
		plateau[6][12].SetType(Case.LDOUBLE);
		plateau[8][2].SetType(Case.LDOUBLE);
		plateau[8][6].SetType(Case.LDOUBLE);
		plateau[8][8].SetType(Case.LDOUBLE);
		plateau[8][12].SetType(Case.LDOUBLE);
		plateau[7][3].SetType(Case.LDOUBLE);
		plateau[7][11].SetType(Case.LDOUBLE);
		//mot compte double
		plateau[1][1].SetType(Case.MDOUBLE);
		plateau[2][2].SetType(Case.MDOUBLE);
		plateau[3][3].SetType(Case.MDOUBLE);
		plateau[4][4].SetType(Case.MDOUBLE);
		plateau[9][9].SetType(Case.MDOUBLE);
		plateau[10][10].SetType(Case.MDOUBLE);
		plateau[11][11].SetType(Case.MDOUBLE);
		plateau[12][12].SetType(Case.MDOUBLE);
		plateau[13][13].SetType(Case.MDOUBLE);
		plateau[1][13].SetType(Case.MDOUBLE);
		plateau[2][12].SetType(Case.MDOUBLE);
		plateau[3][11].SetType(Case.MDOUBLE);
		plateau[4][10].SetType(Case.MDOUBLE);
		plateau[10][4].SetType(Case.MDOUBLE);
		plateau[11][3].SetType(Case.MDOUBLE);
		plateau[12][2].SetType(Case.MDOUBLE);
		plateau[13][1].SetType(Case.MDOUBLE);
		//centre de la grille
		plateau[7][7].SetType(Case.MDOUBLE);



	}


	public String toString()
	{
		String s="";
		s+="_____________________________________________________________\n";
		s+="________________________Scrabble_____________________________\n";
		s+="__A___B___C___D___E___F___G___H___I___J___K___L___M___N___O___\n";
		for(int i=0;i<15;i++)
		{


			for(int j=0;j<15;j++)
			{      

				s+="|"+plateau[i][j].toString();
			}
			s+="|"+(i+1)+"\n";
		}
		s+="_____________________________________________________________\n";
		return s;
	}


	/**
	 * @param Strings (exemple "A10")
	 * La fonction reçoit deux coordonnées en String, les normalise pour avoir les points de la matrice.
	 * Elle test ensuite la validité de la portion correspondante.(par exemple si le sens est de bas en haut ou de droite à gauche, ou simplement
	 * pas car cela ne forme pas un enchainement de cases sur une même ligne/colonne)
	 * @return Si la portion est valide, elle renvoie un tableau correspondant aux cases de la portion. Sinon elle renvoie null
	 */
	public Case[] portion(String coord1, String coord2)
	{
		Case[] res=null;
		int[] coord;
		coord = (normaliserCoord(coord1, coord2));
		int x1 = coord[0], y1 = coord[1], x2 = coord[2], y2 = coord[3], size = 0;

		if(x2 == x1 || y2 == y1) // Si c'est pas une diagonale.
		{
			if(x2 == x1) //si le mot est vertical
			{
				if (y2 > y1)
				{
					size=(y2-y1+1);
					Case[] range = new Case[size];
					for(int i=0; i<size; ++i)
						range[i] = plateau[y1+i][x1];
					res=range;
				}
				else if( y2 == y1) //Les deux coordonnées sont identiques.
				{
					size = 1;
					Case[] range = new Case[size]; range[0]= plateau[y1][x1]; return range;
				}
				else
					res= null; // Les deux coordonnées sont invalides.
			}
			else if(y2 == y1) //si le mot est horizontal
			{
				if( x2 > x1)
				{
					size=(x2-x1+1);
					Case[] range = new Case[size];
					for(int i=0; i<size; ++i)
						range[i] = plateau[y1][x1+i];
					res= range;
				}
			}
		}
		return res;
	}
	/**
	 * @param String (exemple "A10)
	 * Transforme un String de type "lettreChiffre" en deux entiers correspondant aux indices du plateau pour les deux coordonnées.
	 * @return un tab[2] de int avec les indices de coordonnées dans la matrice (de 0 à 14) . [x1, y1]
	 */
	public static int[] normaliserCoord(String coord)
	{
		String p1 = new String (coord.substring(0,1).toUpperCase());
		String p2 = new String (coord.substring(1));
		int[] val = new int[2];
		val[0] = (int)(p1.charAt(0)) - (int)("A".charAt(0));
		val[1] = Integer.parseInt(p2) - 1;
		return val;
	}
	/**
	 * @param Strings (exemple "A10)
	 * Transforme deux Strings de type "lettreChiffre" en deux fois deux entiers correspondant aux indices du plateau pour les deux coordonnées.
	 * @return un tab[4] de int avec les indices de coordonnées dans la matrice (de 0 à 14) . [x1, y1, x2, y2]
	 */
	public static int[] normaliserCoord(String coord1, String coord2)
	{
		int[] val = new int[4]; int[] v1 = normaliserCoord(coord1); int[] v2 = normaliserCoord(coord2);
		val[0] = v1[0];
		val[1] = v1[1];
		val[2] = v2[0];
		val[3] = v2[1];
		return val;
	}



	/** Renvoit la séquence de cases qui est avant la séquence coord1 - coord2 et qui contient des lettres */
	public Case[] lettersBefore(String coord1, String coord2)
	{
		Case[] res = null;
		int[] coord_int1 = normaliserCoord(coord1);
		int[] coord_int2 = normaliserCoord(coord2);
		if (coord_int1[0] == coord_int2[0]) // Vertical
		{
			int y = coord_int1[1] - 1;
			while (y != -1 && getCase(coord_int1[0], y).hasJeton())
				--y;
			y++;
			res = new Case[coord_int1[1] - y];
			for (int i = 0 ; y != coord_int1[1] ; y++, i++)
				res[i] = getCase(coord_int1[0], y);

		}
		else // (coord_int1[1] == coord_int2[1]) => Horizontal
		{
			int x = coord_int1[0] - 1;
			while (x != -1 && getCase(x, coord_int1[1]).hasJeton())
				--x;
			x++;
			res = new Case[coord_int1[0] - x];
			for (int i = 0 ; x != coord_int1[0] ; x++, i++)
				res[i] = getCase(x, coord_int1[1]);
		}

		return res;
	}

	/**retourne une case suivant ces coordonnées dans la grille
	 * @param x
	 * @param y
	 * @return la case de la grille aux coord(x,y)
	 */
	private Case getCase(int x, int y) {
		return  plateau[x][y];

	}


	/** Renvoit la séquence de cases qui est après la séquence coord1 - coord2 et qui contient des lettres */
	public Case[] lettersAfter(String coord1, String coord2)
	{
		Case[] res = null;
		int[] coord_int1 = normaliserCoord(coord1);
		int[] coord_int2 = normaliserCoord(coord2);
		if (coord_int1[0] == coord_int2[0]) // Vertical
		{
			int y = coord_int2[1] + 1;
			while (y != 15 && getCase(coord_int2[0], y).hasJeton())
				++y;
			y--;
			res = new Case[y - coord_int2[1]];
			for (int i = 0 ; y != coord_int2[1] ; y--, i++)
				res[res.length - i] = getCase(coord_int2[0], y);
		}
		else // (coord_int1[1] == coord_int2[1]) => Horizontal
		{
			int x = coord_int2[0] + 1;
			while (x != 15 && getCase(x, coord_int2[1]).hasJeton())
				++x;
			x--;
			res = new Case[x - coord_int2[0]];
			for (int i = 0 ; x != coord_int2[0] ; x--, i++)
				res[res.length - i] = getCase(x, coord_int2[1]);
		}
		return res;
	}
	public String casesToString(Case[] cases)
	{
		String res = "";
		for (Case caseCourante : cases)
			if (caseCourante.hasJeton())
				res += caseCourante.GetJeton().GetLetter();
		return res;
	}


	/**
	 *Doit retourner la séquence de cases perpendiculaires à [coord_debut, coord_fin] qui passe par coord
	 *Les cases doivent tous avoir des lettres posées dessus.
	 *Si il n'y a pas de lettres environnantes. Seul la case correspondant à coord est rendu.
	 *Une portion perpendiculaire d'une case sans lettres renvoie cette case.
	 */
	public Case[] portionPerpendiculaire(String coord_debut, String coord_fin, Case caseCourante)
	{
		int[] coordMot; int[] coordLettre;
		coordMot = (normaliserCoord(coord_debut, coord_fin));
		coordLettre = getCoordCase(caseCourante);

		int x1 = coordMot[0], x2 = coordMot[2], sizeSection = 0;
		int xL = coordLettre[0], yL = coordLettre[1];
		int indX = xL, indY = yL, indSectX_deb = 0, indSectY_deb = 0, indSectX_fin = 0, indSectY_fin = 0;

		Case[] section;

		if(x1 == x2) // si le mot est vertical
		{
			indSectY_deb = yL; //La section sera donc horizontale.
			indSectY_fin = yL;
			indSectX_deb = xL;
			indSectX_fin = xL;
			if(--indX < 0) indX = 0; //on prends la lettre au dessus de la caseCourante.
			while (plateau[yL][indX].hasJeton()) //On va à gauche jusqu'a trouver une case sans lettre
			{
				indX--;
				if(indX < 0) { indX = 0; indSectX_deb = 0;  break; }
				indSectX_deb = indX+1;  // on donne comme indice la case d'avant celle sans lettre.
			}

			indX = xL;
			if(++indX > 14) indX = 14;
			while (plateau[yL][indX].hasJeton())
			{
				indX++;
				if(indX > 14) { indX = 14; indSectX_fin = 14; break; }
				indSectX_fin= indX-1;  // on donne comme indice la case d'avant celle sans lettre.
			}

			sizeSection = indSectX_fin - indSectX_deb +1;
			section = new Case[sizeSection];
			for(int i=0; i<sizeSection; ++i)
				section[i] = plateau[yL][indSectX_deb+i];
			return section;
		}
		else //si le mot est horizontal
		{
			indSectX_deb = xL; //La section sera donc verticale.
			indSectX_fin = xL;
			indSectY_deb = yL;
			indSectY_fin = yL;
			if(--indY < 0) indY = 0; //on prends la lettre au dessus de la caseCourante.
			while (plateau[indY][xL].hasJeton()) //On remonte jusqu'a trouver une case sans lettre
			{
				indY--;
				if(indY < 0) { indY = 0; break; }
				indSectY_deb = indY+1;  // on donne comme indice la case d'avant celle sans lettre.
			}
			indY = yL;
			if(++indY > 14) indY = 14;
			while (plateau[indY][xL].hasJeton())
			{
				indY++;
				if(indY > 14) { indY = 14; break; }
				indSectY_fin = indY-1;
			}
			sizeSection = indSectY_fin - indSectY_deb +1;
			section = new Case[sizeSection];
			for(int i=0; i<sizeSection; ++i)
				section[i] = plateau[indSectY_deb+i][xL];
			return section;
		}
	}

	/**
	 * @param Prend un case en paramètre.
	 * @return Retourne un tableau de int composé des valeurs t[0]= coord x et t[1]= coord y
	 */
	public int[] getCoordCase(Case c)
	{
		int[] t = null;
		for(int j=0; j< 15; ++j)
		{
			for(int i=0; i<15 ; ++i)
			{
				if(plateau[j][i] == c)
				{
					t = new int[2]; t[0] = i; t[1] = j;
				}
			}
		}
		return t;
	}


	/**ajoute un Jeton a la grille suivant une case auxiliaire creer pour analyser le coup dans la classe Move
	 * @param case1
	 */
	public void setPlateau(Case case1)
	{
		plateau[case1.GetX()][case1.GetY()].SetJeton(case1.GetJeton());	
	}



}

